   /***********************策略************************/


   function validFails(that, opt) {
       that.setAttribute("class", opt.errorClass);
       // after(this, this.name + "-error", opt.errorElem, opt.errorClass, opt.errorMsg);
       after({
           elem: that,
           id: that.name + "-error",
           errorElem: opt.errorElem,
           errorClass: opt.errorClass,
           errorMsg: opt.errorMsg
       })
   };
   String.prototype.trim = function() {
       return this.replace(/(^\s+)|(\s+$)/g, '')
   };

   function validSuccess(that) {
       that.setAttribute("class", "");
       removeClass(that.name + "-error");
   }

   function getId(id) {
       return document.getElementById(id);
   }

   function after(opt) {
       if (getId(opt.id)) {
           var d = getId(opt.id)
           d.setAttribute("class", opt.errorClass);
           d.innerHTML = opt.errorMsg;
       }
   };

   function removeClass(id) {
       //console.log(id)
       getId(id).setAttribute("class", "");
       getId(id).innerHTML = "";
   }
   //实现after功能
   function insertAfter(newEl, targetEl) {
       // console.log(newEl,targetEl)
       var parentEl = targetEl.parentNode;

       if (parentEl.lastChild == targetEl) {
           parentEl.appendChild(newEl);
       } else {
           parentEl.insertBefore(newEl, targetEl.nextSibling);
       }
   }
   /************************validator类************************/
   var Validator = function(opt) {
       var that = this;
       this.obj = obj = this;
       that.opt = opt;
       that.form = opt.id;
       that.Submit = this.opt.Submit;
       this.opt.id.setAttribute("novalidate", "novalidate");
       this.rules = {
           required: true,
           email: true,
           maxlength: 5,
           number: true,
           isMobile: true

       };
       this.event_ID = 1;

       this.message = {
           required: "不能为空",
           email: "必须是邮箱",
           malength: "长度不对",
           minLength: "最小长度不对",
           number: "必须是数字",
           isMobile: "必须是手机号码",
           min: "输入值需请小于或等于{0}.",
           range: "Please enter a value between {0} and {1}.",

       };
       //最终提示
       /*
         {userName: {minLength: "最小长度不对",required: "用户名不能为空"}, 
         password: {minLength: "最小长度不对",required: "用户名不能为空"}}
       */
       this.endMessage = {};

       //定义策略类
       //规则返回：如果正确放回true，否则false
       this.strategies = {
           required: function(opt) {
            //that.opt.rules.maPhone.required()
               var name=this.name;
              // console.log(this,(that.opt.rules[name].required&&typeof that.opt.rules[name].required=="function")&&that.opt.rules[name].required());
               if((that.opt.rules[name].required&&typeof that.opt.rules[name].required=="function")&&that.opt.rules[name].required()==false){
                  return false;
               }
               return this.value.trim().length > 0;
           },
           minLength: function(opt) {
               return obj.optional(this) || this.value.length > opt.rule;
           },
           range: function(opt) {
               var that = this;
               return obj.optional(this) || (parseFloat(that.value) >= opt.rule[0]) && (parseFloat(that.value) <= opt.rule[1]);
           }

       };

   };

   Validator.prototype.init = function() {
           var opt = this.opt;
           var that = this;
           this.dom(); //添加dom
           this.endMessage = this.extend(opt.rules, this.message); //覆盖提示
           //这里是获取不到通过addMethod添加的规则的提示的
           that.event(opt); //添加事件触发
           this.submit();
       }
       // Validator.prototype.showErrors = function() {

   // };
   Validator.prototype.dom = function(elem, opts) {
           // {
           //                elem: that,
           //                id: that.name + "-error",
           //                errorElem: opt.errorElem,
           //                errorClass: opt.errorClass,
           //                errorMsg: opt.errorMsg
           //            }
           var opt = this.opt;

           for (var n in opt.rules) {
               // console.log(this.opt.message[n])
               var elem = document.getElementsByName(n)[0];
               if (!getId(elem.name + "-error")) {
                   var d = document.createElement(opt.errorElement);
                   d.setAttribute("id", elem.name + "-error");
                   d.setAttribute("class", opt.errorClass);
                   insertAfter(d, elem);
               }
           }

       }
       /*返回单个input的提示json
         opt:客户端传入规则列表
         defaultOpt:系统自带初始值
       */
   Validator.prototype.extend = function(rule, defaultOpt) {
       var optMsg = {};
       for (var n in rule) {
           optMsg[n] = {};
           for (m in rule[n]) {

               getId(n + "-error").errorMsg
                   //如果存在提示就替换初始的
                   //  console.log(n)
               if (this.opt.message[n] && this.opt.message[n][m]) {
                   optMsg[n][m] = this.format(this.opt.message[n][m], rule[n][m]);

               } else if (this.endMessage[n] && this.endMessage[n][m]) {
                   /*这一个操作是重复的,去掉 去掉*/
                   optMsg[n][m] = this.endMessage[n][m];
               } else {
                   optMsg[n][m] = this.format(this.message[m], rule[n][m]);
               }
           }
       }
       return optMsg;
   }
   Validator.prototype.runRules = function() {
           var opt = this.opt;
           var b = true;

           for (var n in opt.rules) {

               var elem = document.getElementsByName(n)[0];

               var d = this.getRule(elem, opt.rules[n], this.endMessage[n])
               if (d == false) {
                   b = false;
               }
           }
           return b;
       }
       /*
          @param elem 节点
          @param rule 对应节点的所有规则
          @param msg对应节点的所有错误提示 
       */
   Validator.prototype.getRule = function(elem, rule, msg) {
       var tmp = true;
       var that = this;
       //   console.log(msg)
       for (var n in rule) {
           //如果值是false，直接跳过校验
           if (typeof rule[n] == "function" && rule[n]() == false) {
               validSuccess(elem)
                   //每次验证的时候都执行下函数
               continue;
           }
           console.log(elem)
           if (rule[n] == false) {
               continue;
           }

           var b = that.strategies[n].apply(elem, [{
               val: elem.value,
               rule: rule[n]
           }]);
           if (!b) {
               validFails(elem, {
                   elem: elem,
                   id: elem.name + "-error",
                   errorElem: that.opt.errorElem,
                   errorClass: that.opt.errorClass,
                   errorMsg: msg[n]
               });
           } else {
               validSuccess(elem)
           }

           if (b == false) {
               b = false;
               //只要有一个条件不符合就中断下一个条件匹配
               break;
           }

       }
       return b;
   }


   //事件触发校验
   Validator.prototype.event = function(opt) {
           var that = this;
           console.log(opt.rules)

           for (var n in opt.rules) {
               (function(n) {
                   var elem = document.getElementsByName(n)[0];
                   console.log(elem)
                       // elem.onchange = elem.onblur = elem.onpropertychange = elem.oninput = function() {
                       //     //  that.getRule(this, opt.rules[this.name], that.endMessage[n]);
                       //     that.elements(this);
                       // }
                   that.addEvent(elem, 'change,propertychange,input', function() { that.elements(elem); });
                   // that.addEvent(elem, 'propertychange', function() { that.elements(elem); });
                   // that.addEvent(elem, 'oninput', function() { that.elements(elem); });
               })(n);
           }

       }
       /*
         主动触发校验
         @param {dom object} 如果没有传参 默认校验所有，否则校验指定dom
       */
   Validator.prototype.validx = function(elem) {
       var that = this;
       if (elem) {

           // return this.getRule(elem[0], this.opt.rules[elem[0].name], that.endMessage[elem[0].name]);
       }
       // return this.runRules();
   };
   //与valid类似
   Validator.prototype.elements = function(elem) {
       var result = true;
       //只校验单独的input

       var inputName = elem.name;
       var rules = this.opt.rules[inputName];
       console.log(elem)
       for (var n in rules) {

           //表单失去焦当的时候不校验是否为空
           // if (n == 'required') {
           //     continue;
           // }

           var b = this.strategies[n].apply(elem, [{ rule: rules[n] }])
           if (!b) {
               validFails(elem, {
                   elem: elem,
                   id: elem.name + "-error",
                   errorElem: this.opt.errorElem,
                   errorClass: this.opt.errorClass,
                   errorMsg: this.endMessage[inputName][n]
               });
               console.log('fails');
               result = false;
               break;
           } else {
               validSuccess(elem)
               console.log('succes');
           }

       }
       return result;
   }
   Validator.prototype.valid = function(elem,attr) {
       var result = true;
       //只校验单独的input
       if (elem) {
           var inputName = elem.name;
           var rules = this.opt.rules[inputName];
          // if(attr){
          //   if(!that.opt.rules[inputName].required||(that.opt.rules[inputName].required&&typeof that.opt.rules[inputName].required=="function")&&that.opt.rules[inputName].required()==false){
          //      return false;
          //   }
          // }
           for (var n in rules) {

               //表单失去焦当的时候不校验是否为空
               if (n == 'required') {
                   continue;
               }

               var b = this.strategies[n].apply(elem, [{ rule: rules[n] }])
               if (!b) {
                   validFails(elem, {
                       elem: elem,
                       id: elem.name + "-error",
                       errorElem: this.opt.errorElem,
                       errorClass: this.opt.errorClass,
                       errorMsg: this.endMessage[inputName][n]
                   });

                   result = false;
                   break;
               } else {

                   validSuccess(elem)
               }

           }

       } else {
           /*校验所有input是否必填|如果填充内容就校验相应的规则*/
           for (var m in this.opt.rules) {

               var inputName = m;
               var rules = this.opt.rules[m];

               var elem = document.getElementsByName(inputName)[0];

               //长度为空，并且显性设置必填
               //  console.log(elem,rules['required'],(rules['required'] == true || (typeof rules['required'] == "function" && rules['required']()==true)  ))
               //elem.value.trim().length===0 && (
               if (rules['required'] == true || (typeof rules['required'] == "function" && rules['required']() == true)) {
                   var d = this.optional(elem);
                   if (!d) {
                       validSuccess(elem)
                   } else {
                       // console.log(m, this.endMessage[inputName])
                       validFails(elem, {
                           elem: elem,
                           id: elem.name + "-error",
                           errorElem: this.opt.errorElem,
                           errorClass: this.opt.errorClass,
                           errorMsg: this.endMessage[inputName]['required']
                       });
                       result = false;
                   }
               } else if (elem.value.trim().length) {
                   // console.log(elem)
                   Inner: for (var n in rules) {
                       //必填校验不校验
                       if (n == 'required') {
                           continue;
                       }
                       var b = this.strategies[n].apply(elem, [{ rule: rules[n] }]);
                       // console.log(b)
                       if (!b) {
                           validFails(elem, {
                               elem: elem,
                               id: elem.name + "-error",
                               errorElem: this.opt.errorElem,
                               errorClass: this.opt.errorClass,
                               errorMsg: this.endMessage[inputName][n]
                           });
                           result = false;
                           break Inner;
                       } else {
                           //  console.log(elem)
                           validSuccess(elem)
                       }

                   }
               }
           }

       }
       // console.log(result)
       return result;
   }
   Validator.prototype.validAll = function(elem) {

   }

   /*
        @param name {string} 自定义规则name
        @param fn {fn}
            fn:
            @param value 元素值
            @param element 元素
            @param param 自定义字符串
   */
   Validator.prototype.addMethod = function(name, fn, errorMsg) {

       var opt = this.opt;
       var callback;
       var obj = this; //验证表单对象

       /*add时候的提示文字不应该放到 trategies函数里面*/
       // obj.endMessage[obj.name] = {};
       // obj.endMessage[obj.name][name] = obj.format(errorMsg, obj.opt["rules"][obj.name][name]);
       //  console.log("**************")
       for (var n in opt.rules) {
           //n是表单name
           for (var m in opt.rules[n]) {
               if (m == name) {
                   //m规则名
                   // console.log(m)
                   obj.endMessage[n] = {};
                   obj.endMessage[n][m] = obj.format(errorMsg, obj.opt["rules"][n][m]);
               }
           }
       }
       //console.log( obj.endMessage)

       obj.strategies[name] = function(opt) {
           //这里的this是节点
           var that = this;

           if (typeof fn == "function") {
               //如果是数组并且长度为2，就提供param参数给回调函数
               if (obj.opt["rules"][that.name][name] instanceof Array && obj.opt["rules"][that.name][name].length == 2) {
                   callback = fn(that.value, that, obj.opt["rules"][that.name][name]);
               } else {
                   callback = fn(that.value, that);
               }


           } else {
               throw error("addMethod函数第二个参数为函数！");
               return false;
           }
           return callback;
       }

   }
   Validator.prototype.submit = function(e) {
           var that = this;


           that.form.onsubmit = function(event) {
               event.preventDefault();
               // console.log(that.endMessage)
               var target = event.target || event.srcElement;
               if (that.valid()) {
                   //将要提交的数据
                   var data = {};
                   try {
                       for (var n = 0; n < target.childElementCount; n++) {
                           if (target[n]) {
                               if (target[n].type == "checkbox") {
                                   if (!data[target[n].name]) {
                                       data[target[n].name] = [];
                                   }
                                   if (data[target[n].name] && target[n].checked) {
                                       data[target[n].name].push(target[n].value);
                                   }
                               } else {
                                   data[target[n].name] = target[n].value;
                               }

                           }
                       }

                       if (that.opt.Submit) {

                           that.Submit = that.opt.Submit(data);
                       }
                   } catch (exception) {   
                       console.error(exception)
                   }
               }
               return false;
           }

       }
       /*
        @param str {string} 提示文字
        @param data {array||string} 校验规则
       */
   Validator.prototype.format = function(str, data) {
       if (!(new RegExp(/\{(\d+)\}/g).test(str))) {
           return str;
       }
       var tmp;
       if (typeof data === "string") {
           tmp = str.replace(/\{(\w+)\}/g, data);

       }

       if (data instanceof Array) {
           tmp = str.replace(/\{(\w+)\}/g, function(match, key) {
               // console.log(match, key)
               // console.log(data)
               return typeof data[key] === undefined ? "" : data[key];
           });
       }
       return tmp;
   }
   Validator.prototype.optional = function(element) {
       var val = element.value;
       //这里是取反的
       return !this.strategies.required.apply(element, [val]) && "dependency-mismatch";
   }

   //跨浏览器添加事件绑定
   Validator.prototype.addEvent = function(obj, type, fn) {
       if (typeof obj.addEventListener != 'undefined') {
           if (/,/.test(type)) {
               var type=type.split(',');
               for (var i = 0; i <type.length;i++) {
                   (function() {
                      console.log(type[i])
                       obj.addEventListener(type[i].trim(), fn, false);
                   })(i)
               }
           }

       }
       //  else {
       //     //创建一个存放事件的哈希表(散列表)
       //     if (!obj.events) obj.events = {};
       //     //第一次执行时执行
       //     if (!obj.events[type]) {
       //         //创建一个存放事件处理函数的数组
       //         obj.events[type] = [];
       //         //把第一次的事件处理函数先储存到第一个位置上
       //         if (obj['on' + type]) obj.events[type][0] = fn;
       //     }
       //     //从第二次开始我们用事件计数器来存储
       //     obj.events[type][this.event_ID++] = fn;
       //     //执行事件处理函数
       //     obj['on' + type] = function() {
       //         for (var i in obj.events[type]) {
       //             obj.events[type][i](); //顺序执行已经解决
       //         }
       //     };
       // }
   }
